home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
msysjour
/
vol07
/
01
/
autotest
/
tester.c
< prev
next >
Wrap
Text File
|
1991-12-31
|
18KB
|
469 lines
/****************************************************************************
PROGRAM: Tester.c
PURPOSE: DLL that records and plays back test scripts for Windows
applications
FUNCTIONS:
LibMain() - automatic initialization function that performs
one-time start-up processing.
WEP() - DLL termination function; performs DLL cleanup before
it is unloaded.
Tester() - saves instance handle and creates main window
JournalRecordHook() - A WH_JOURNALRECORD system hook that records
keyboard and mouse event messages from the
system queue
JournalPlaybackHook() - A WH_JOURNALPLAYBACK system hook that plays
back previously recorded messages
*******************************************************************************/
#include <windows.h>
#include "tester.h"
#include "testinc.h"
static FARPROC fnNextJrnlHookFunc = NULL;
static GLOBALHANDLE hMemTestScript = NULL;
static TESTRESULT HaltStatus = TEST_OK;
static HWND hWnd2Notify;
static WORD wMsgtoSend;
static char str[MAXNUMBUFFS*BUFFERSIZE];
static char strtemp[BUFFERSIZE];
static LPSTR lpTraceFileName = NULL;
static OFSTRUCT OfStruct; /* information from OpenFile() */
static HANDLE hFile;
static EVENTQSTAT EventStats;
static BOOL TraceOn;
BOOL FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSeg, WORD cbHeapSize,
LPSTR lpszCmdLine)
{
/* if DLL data seg is MOVEABLE */
if (cbHeapSize != 0)
UnlockData(0);
return(TRUE); /* Initialization successful */
}
int FAR PASCAL WEP(int nParameter)
{
if (nParameter == WEP_SYSTEM_EXIT)
return (1);
else
if (nParameter == WEP_FREE_DLL)
/* DLL use count is zero. Every application that had loaded the DLL
has freed it. */
return (1);
else
/* Undefined value. Ignore it.*/
return (1);
}
/**************************************************************************
ROUTINE: Tester.c
PURPOSE: Routine that is called by MainWndProc that installs a
WH_JOURNALRECORD hook, and initiates the recording of events.
It also installs the WH_JOURNALPLAYBACK hook to playback these
pre-recorded events.
***************************************************************************/
TESTRESULT FAR PASCAL Tester(TESTMODE AutotestMode, HANDLE hMemEvents,
HWND hWndtoNotify, WORD wMsg,
BOOL TraceOnFlag, LPSTR lpFileName)
{
TESTRESULT TesterReturnCode = TEST_OK;
LPEVENTMSGMSG lpEvent;
unsigned int EventQIndex;
switch (AutotestMode)
{
case IDD_STARTRECORD:
/* Save the hWnd to send any stop messages to */
hWnd2Notify = hWndtoNotify;
wMsgtoSend = wMsg;
HaltStatus = TEST_OK;
/* Allocate the memory to hold the test event queue */
hMemTestScript = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
MAXEVENTQSIZE * sizeof(EVENTMSG));
if (hMemTestScript == NULL)
{
TesterReturnCode = TEST_NOMEMORY;
HaltStatus = TEST_NOMEMORY;
}
else
{
/* Initialize the event queue header */
EventStats.wNumEvents = 0;
EventStats.wNumEventsPlayed = 0;
EventStats.dwStartPlaybackTime = 0;
EventStats.wTimebetEvents = 0;
EventStats.wPercentofTime = 0;
EventStats.wMemUtilized = 0;
EventStats.wNumEventsBypassed = 0;
EventStats.wNumIterationsPlayed = 0;
/* Start recording events */
fnNextJrnlHookFunc = SetWindowsHook(WH_JOURNALRECORD,
(FARPROC)JournalRecordHook);
TesterReturnCode = TEST_OK;
}
break;
case IDD_STOPRECORD:
if (hMemTestScript == NULL)
/* Recording not made */
TesterReturnCode = TEST_INACTIVE;
else
{
/* Stop Recording Events */
UnhookWindowsHook(WH_JOURNALRECORD, (FARPROC)JournalRecordHook);
/* Adjust the timing in the event chain according to the users
Request */
lpEvent = (LPEVENTMSGMSG)GlobalLock(hMemTestScript);
if (TraceOnFlag)
{
TraceOn = TRUE;
lpTraceFileName = lpFileName;
/* Write out the recorded events to the trace file */
for (EventQIndex= 1; EventQIndex < EventStats.wNumEvents;
EventQIndex++)
{
lpEvent[EventQIndex].time -= lpEvent[0].time;
/* Write out the events to the tracefile */
wsprintf(str,
"Recorded Event MSG %d= %d; paramL= %x; paramH= %x; time= %ld\n",
EventQIndex, lpEvent[EventQIndex].message,
lpEvent[EventQIndex].paramL,
lpEvent[EventQIndex].paramH,
lpEvent[EventQIndex].time);
WriteFile(lpTraceFileName, (LPSTR)&str);
}
}
else
{
TraceOn = FALSE;
lpTraceFileName = NULL;
}
/* Don't wait to playback the first event */
lpEvent[0].time = 0;
GlobalUnlock(hMemTestScript);
TesterReturnCode = TEST_OK;
/* Signal to the Autotest app that recording has stopped */
SendMessage(hWnd2Notify, wMsgtoSend, hMemTestScript, HaltStatus);
hMemTestScript = NULL;
}
break;
case IDD_STARTPLAY:
/* Save the hWnd to send any stop messages to */
hWnd2Notify = hWndtoNotify;
wMsgtoSend = wMsg;
HaltStatus = TEST_OK;
if (TraceOnFlag)
{
TraceOn = TRUE;
lpTraceFileName = lpFileName;
}
else
{
TraceOn = FALSE;
lpTraceFileName = NULL;
}
EventStats.wNumIterations = GetProfileInt("autotest",
"NumberofIterations", 2);
GetProfileString("autotest","FixedTimingFlag","TRUE",
EventStats.FixedTiming, 5 );
if ((EventStats.FixedTiming[0] == 't') ||
(EventStats.FixedTiming[0] == 'T'))
EventStats.wTimebetEvents = GetProfileInt("autotest",
"TimeBetEvents",55);
else
EventStats.wPercentofTime = GetProfileInt("autotest",
"PercentRecordTime", 100);
EventStats.wNumEventstoBypass = GetProfileInt("autotest",
"NumEventstoBypass", 5);
EventStats.wBufferSize = GetProfileInt("autotest","IOBufferSize", 300);
/* Do not allow a buffer size of less than one or
greater than 5*BUFFERSIZE */
if (EventStats.wBufferSize < 1)
EventStats.wBufferSize = 1;
else
if (EventStats.wBufferSize > (15*MAXNUMBUFFS))
EventStats.wBufferSize = 15*MAXNUMBUFFS;
/* Initialize Event Message structure */
EventStats.wNumEventsBuffered = EventStats.wBufferSize;
EventStats.wNumEventsPlayed = 0;
EventStats.wNumIterationsPlayed = 0;
EventStats.wNumEventsBypassed = 0;
if (TraceOn)
{
/* Write the parameters out to the playback trace file */
wsprintf(str, "[autotest]\nNumberofIterations= %d\n",
EventStats.wNumIterations);
WriteFile(lpTraceFileName, (LPSTR)&str);
wsprintf(str, "FixedTimingFlag= %s\n",
(LPSTR)&EventStats.FixedTiming[0]);
WriteFile(lpTraceFileName, (LPSTR)&str);
wsprintf(str, "TimebetEvents= %d\n", EventStats.wTimebetEvents);
WriteFile(lpTraceFileName, (LPSTR)&str);
wsprintf(str, "PercentRecordTime= %d\n", EventStats.wPercentofTime);
WriteFile(lpTraceFileName, (LPSTR)&str);
wsprintf(str, "NumEventstoBypass= %d\n",
EventStats.wNumEventstoBypass);
WriteFile(lpTraceFileName, (LPSTR)&str);
wsprintf(str, "IOBufferSize= %d\n", EventStats.wBufferSize);
WriteFile(lpTraceFileName, (LPSTR)&str);
}
str[0] = NULL;
EventStats.wNumEventsPlayed = 0;
hMemTestScript = (GLOBALHANDLE)hMemEvents;
lpEvent = (LPEVENTMSGMSG)GlobalLock(hMemTestScript);
/* Perform calculations on timings */
for (EventQIndex= 1; EventQIndex < EventStats.wNumEvents;
EventQIndex++)
{
if ((EventStats.FixedTiming[0] == 't') ||
(EventStats.FixedTiming[0] == 'T'))
lpEvent[EventQIndex].time = lpEvent[0].time + (EventQIndex *
EventStats.wTimebetEvents);
else
if (EventStats.wPercentofTime > 0)
lpEvent[EventQIndex].time = (lpEvent[EventQIndex].time *
EventStats.wPercentofTime /100);
else
lpEvent[EventQIndex].time = (lpEvent[EventQIndex].time *
1/100);
}
/* if there are events to playback */
if (EventStats.wNumEvents != 0)
{
/* Initialize time playback is starting */
EventStats.dwStartPlaybackTime = GetTickCount();
GlobalUnlock(hMemTestScript);
/* Start recording events */
fnNextJrnlHookFunc = SetWindowsHook(WH_JOURNALPLAYBACK,
(FARPROC)JournalPlaybackHook);
TesterReturnCode = TEST_OK;
}
else
TesterReturnCode = TEST_NOEVENTS;
break;
case IDD_STOPPLAY:
UnhookWindowsHook(WH_JOURNALPLAYBACK,
(FARPROC)JournalPlaybackHook);
/* Signal to the Autotest app that playback has stopped */
SendMessage(hWnd2Notify, wMsgtoSend, hMemTestScript, HaltStatus);
hMemTestScript = NULL;
break;
}
return (TesterReturnCode);
}
DWORD FAR PASCAL JournalRecordHook (int nCode, WORD wParam,
LPEVENTMSGMSG lpEventMsg)
{
DWORD dwReturnCode;
LPEVENTMSGMSG lpEventEntry;
WORD wNumEvents;
switch (nCode)
{
case HC_ACTION:
/* Check if the number of events exceeds our limit of x'FFFF' */
wNumEvents = EventStats.wNumEvents + 1;
if (wNumEvents == MAXEVENTQSIZE)
{
/* Reached our limit; stop recording */
HaltStatus = TEST_TOOMANYEVENTS;
Tester(IDD_STOPRECORD, 0, 0, 0, TraceOn, (LPSTR)NULL);
}
else
{
/* Append the new event on to the end of the memory block */
lpEventEntry = (LPEVENTMSGMSG)GlobalLock(hMemTestScript);
lpEventEntry[EventStats.wNumEvents] = *lpEventMsg;
EventStats.wNumEvents++;
GlobalUnlock(hMemTestScript);
}
break;
}
dwReturnCode = DefHookProc(nCode, wParam, (LONG)lpEventMsg,
(FARPROC FAR *)&fnNextJrnlHookFunc);
return(dwReturnCode);
}
DWORD FAR PASCAL JournalPlaybackHook (int nCode, WORD wParam,
LPEVENTMSGMSG lpEventMsg)
{
DWORD dwReturnCode = 0;
DWORD dwDelta = 0;
LPEVENTMSGMSG lpEventEntry;
WORD wNumEvntsPlayed;
DWORD dwTempTime = 0;
DWORD dwFreeSpace = 0;
lpEventEntry = (LPEVENTMSGMSG)GlobalLock(hMemTestScript);
switch (nCode)
{
case HC_SKIP:
/* Test if user has pressed control break */
if ((GetAsyncKeyState(VK_CONTROL) & 0x8001)
&& (GetAsyncKeyState(VK_CANCEL) & 0x8001))
{
if (TraceOn)
WriteFile(lpTraceFileName, (LPSTR)&str);
Tester(IDD_STOPPLAY, (HANDLE)NULL, (HWND)NULL, 0, TraceOn,
(LPSTR)NULL);
}
++EventStats.wNumEventsPlayed;
if (EventStats.wNumEventsPlayed > EventStats.wNumEvents)
{
++EventStats.wNumIterationsPlayed;
if (EventStats.wNumIterationsPlayed < EventStats.wNumIterations)
{
EventStats.wNumEventsPlayed = 0;
EventStats.dwStartPlaybackTime = GetTickCount();
}
else
{
if (TraceOn)
WriteFile(lpTraceFileName, (LPSTR)&str);
Tester(IDD_STOPPLAY, (HANDLE)NULL, (HWND)NULL, 0, TraceOn,
(LPSTR)NULL);
}
}
/* if Trace Mode is on then capture information to be written
out to the playback trace file */
if (TraceOn)
{
++EventStats.wNumEventsBypassed;
if (EventStats.wNumEventsBypassed > EventStats.wNumEventstoBypass)
{
/* Write out data to trace file */
dwFreeSpace = GetFreeSpace(GMEM_NOT_BANKED);
--EventStats.wNumEventsBuffered;
/* Buffering required for file I/O */
wsprintf(strtemp, "Iteration= %d, Event= %d, FreeSpace= %lu\n",
EventStats.wNumIterationsPlayed,
EventStats.wNumEventsPlayed, dwFreeSpace);
lstrcat((LPSTR)&str, (LPSTR)&strtemp);
if (EventStats.wNumEventsBuffered == 0)
{
WriteFile(lpTraceFileName, (LPSTR)&str);
EventStats.wNumEventsBuffered = EventStats.wBufferSize;
str[0] = NULL;
}
EventStats.wNumEventsBypassed = 0;
}
}
break;
case HC_GETNEXT:
/* Copy the next event in the event queue into the EVENTMSG
structure */
wNumEvntsPlayed = EventStats.wNumEventsPlayed;
*((LPEVENTMSGMSG)lpEventMsg) = lpEventEntry[wNumEvntsPlayed];
/* Add time delta (Event'n' - Event0) back to Start Playing time */
((LPEVENTMSGMSG)lpEventMsg)->time += EventStats.dwStartPlaybackTime;
/* All times are expressed in terms of elapsed time in millisecs since
system start We have used up some time doing all this processing */
dwReturnCode = ((LPEVENTMSGMSG)lpEventMsg)->time - GetTickCount();
if ((signed long)dwReturnCode < 0)
dwReturnCode = 0;
break;
}
GlobalUnlock(hMemTestScript);
dwReturnCode = DefHookProc(nCode, wParam, (LONG)lpEventMsg,
(FARPROC FAR *)&fnNextJrnlHookFunc);
return(dwReturnCode);
}
BOOL WriteFile(LPSTR lpWrFileName, LPSTR lpBuffer)
{
HANDLE hFile;
OFSTRUCT OfStruct; /* information from OpenFile() */
WORD wLength;
char wrstring[255];
/* Check if file exists first */
if (-1 == (hFile = OpenFile(lpWrFileName, (LPOFSTRUCT) &OfStruct,
OF_READWRITE | OF_EXIST)))
{
/* Create it if it does not */
if (-1 == (hFile = OpenFile(lpWrFileName, (LPOFSTRUCT) &OfStruct,
OF_CREATE | OF_PROMPT | OF_CANCEL)))
{
wsprintf(wrstring,
"Tester; WriteFile; hWnd2Notify = %x; File %s not found",
hWnd2Notify, lpWrFileName);
MessageBox(hWnd2Notify, wrstring, "DEBUG", MB_APPLMODAL |
MB_OK | MB_ICONHAND);
return FALSE;
}
}
else
/* open the existing file */
if (-1 == (hFile = OpenFile(lpWrFileName, (LPOFSTRUCT) &OfStruct,
OF_READWRITE | OF_REOPEN)))
{
wsprintf(wrstring,
"WriteFile; hWnd2Notify = %x; Cannot reopen File %s to disk",
hWnd2Notify, lpWrFileName);
MessageBox(hWnd2Notify, wrstring, "DEBUG", MB_APPLMODAL |
MB_OK | MB_ICONHAND);
return FALSE;
}
/* Make sure this writes out to the file OK */
wLength = lstrlen(lpBuffer);
/* Position the file pointer at the end of the file */
_llseek(hFile, STARTPOSITION, ENDOFFILE);
/* append string to end of file */
if (wLength != _lwrite(hFile, lpBuffer, wLength))
{
_lclose(hFile);
wsprintf(wrstring,
"WriteFile; hWnd2Notify = %x; Cannot write File %s to disk",
hWnd2Notify, lpWrFileName);
MessageBox(hWnd2Notify, wrstring, "DEBUG", MB_APPLMODAL |
MB_OK | MB_ICONHAND);
return FALSE;
}
else
{
_lclose(hFile);
}
return TRUE;
}